package org.example;

import org.openjdk.jol.info.ClassLayout;

import java.util.concurrent.TimeUnit;

public class Main16 {

    public static void main(String[] args) throws InterruptedException {
        //-XX:-UseBiasedLocking 关闭偏向锁，只研究轻量级锁和重量级锁
        User user = new User();
        System.out.println("--MAIN--:" + ClassLayout.parseInstance(user).toPrintable());// 无锁
        Thread thread1 = new Thread(() -> {
            synchronized (user) {
                System.out.println("--THREAD1--:" + ClassLayout.parseInstance(user).toPrintable()); //THREAD1获取锁之后，直接从无锁升级到轻量级锁
                try {
                    TimeUnit.SECONDS.sleep(5); //开始休眠五秒，这个时候THREAD1还没有走完同步代码块，所以还没有释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread thread2 = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2); //THREAD2 先睡眠2秒，保证THREAD1已经获取到锁，造成锁对象的资源竞争。
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (user) { //升级为重量级锁
                System.out.println("--THREAD2--:" + ClassLayout.parseInstance(user).toPrintable());
            }
        });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        TimeUnit.SECONDS.sleep(3);
        System.out.println(ClassLayout.parseInstance(user).toPrintable());
        //在线程1持有轻量级锁的情况下，线程2尝试获取锁，导致资源竞争，使轻量级锁升级到重量级锁。
        // 在两个线程都运行结束后，可以看到对象的状态恢复为了无锁不可偏向状态，在下一次线程尝试获取锁时，会直接从轻量级锁状态开始。
        //上面在最后一次打印前将主线程休眠3秒的原因是锁的释放过程需要一定的时间，如果在线程执行完成后直接打印对象内存布局，对象可能仍处于重量级锁状态。
    }
}


class User {
    private String username;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
